package com.spring.demo.init.db;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.ejb.HibernatePersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * jpa 数据库配置
 * 
 * @author sean
 * 
 */
@Configuration
@PropertySource({ "classpath:db/jpaJdbc.properties" })
@EnableTransactionManagement
@EnableJpaRepositories("com.spring.demo.core.dao.jpa")
public class JpaDatabaseConfig {

	// jdbc config
	@Value("${jdbc.driverClass}")
	private String DB_DRIVER_CLASS_NAME;

	@Value("${jdbc.username}")
	private String DB_USERNAME;

	@Value("${jdbc.password}")
	private String DB_PASSWORD;

	@Value("${jdbc.url}")
	private String DB_URL;

	// hibernate properties
	@Value("${hibernate.dialect}")
	private String HIBERNATE_DIALECT;

	@Value("${hibernate.show_sql}")
	private String HIBERNATE_SHOW_SQL;

	@Value("${hibernate.hbm2ddl.auto}")
	private String HIBERNATE_HBM2DDL_AUTO;
	// jpa packages to scan
	private static final String JPA_PACKAGES_TO_SCAN = "com.spring.demo.core.entity";

	@Bean(name = "jpaDataSource")
	public DataSource jpaDataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();
		dataSource.setDriverClassName(DB_DRIVER_CLASS_NAME);
		dataSource.setUrl(DB_URL);
		dataSource.setUsername(DB_USERNAME);
		dataSource.setPassword(DB_PASSWORD);

		return dataSource;
	}

	@Bean
	@Autowired
	public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(
			@Qualifier("jpaDataSource") DataSource dataSource) {
		LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
		bean.setDataSource(dataSource);
		bean.setPersistenceProviderClass(HibernatePersistence.class);
		bean.setJpaProperties(hibernateProperties());
		bean.setPackagesToScan(JPA_PACKAGES_TO_SCAN);

		return bean;
	}

	@Bean(name = "transactionManager")
	@Autowired
	public JpaTransactionManager transactionManager(
			LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
		JpaTransactionManager manager = new JpaTransactionManager();
		manager.setEntityManagerFactory(entityManagerFactoryBean.getObject());

		return manager;
	}

	private Properties hibernateProperties() {
		Properties prop = new Properties();
		prop.setProperty("hibernate.dialect", HIBERNATE_DIALECT);
		prop.setProperty("hibernate.show_sql", HIBERNATE_SHOW_SQL);
		prop.setProperty("hibernate.hbm2ddl.auto", HIBERNATE_HBM2DDL_AUTO);

		return prop;
	}

	@Bean
	public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
		return new PropertySourcesPlaceholderConfigurer();
	}
}
